package com.fone.player.airone;

import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;

import org.apache.http.HttpResponse;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.util.EntityUtils;

import com.fone.player.util.L;

/**
 * airplay投放
 * 
 * @author kongxiaojun
 * @since 2014-6-24
 */
public class FAirPlay {

	public static int PLAYSTATE_PLAYING = 1;
	public static int PLAYSTATE_TRANSITIONING = 2;
	public static int PLAYSTATE_PAUSED_PLAYBACK = 3;
	public static int PLAYSTATE_STOPPED = 4;
	public static int PLAYSTATE_UNKNOWN = -1;

	private static final String TAG = "FAirPlay";
	private static final String USER_AGENT = "iTunes/10.6 (Macintosh; Intel Mac OS X 10.7.3) AppleWebKit/535.18.5";

	public static final int RS_OK = 0;
	public static final int RS_ERROR = -1;

	private static DefaultHttpClient httpclient = new DefaultHttpClient();

	/**
	 * airplay open
	 * 
	 * @param ip
	 *            ipv4address
	 * @param port
	 *            port default 7000
	 * @param file
	 *            playback file url
	 * @param startPosition
	 *            start postion from min is 0 max 1
	 * @return int result
	 * @throws
	 */
	public static int open(String ip, int port, String file, float startPosition) {
		L.v(TAG, "airplay open : " +file);
		if (port <= 0) {
			port = 7000;
		}
		try {
			String url = new URI(file).toASCIIString();
			HttpPost request = new HttpPost("http://" + ip + ":" + port + "/play");
			request.addHeader("Content-Type", "text/parameters");
			request.addHeader("User-Agent", USER_AGENT);
			request.setEntity(new StringEntity("Content-Location: " + url + "\nStart-Position: "+startPosition+"\n\n"));
			HttpResponse httpResponse = httpclient.execute(request);
			L.v(TAG, "airplay open result code : " + httpResponse.getStatusLine().getStatusCode());
			L.v(TAG, "airplay open result : " + EntityUtils.toString(httpResponse.getEntity()));
			if (httpResponse.getStatusLine().getStatusCode() != 200) {
				return RS_ERROR;
			} else {
				return RS_OK;
			}
		} catch (ClientProtocolException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} catch (URISyntaxException e) {
			e.printStackTrace();
		}
		return RS_ERROR;
	}

	/**
	 * seek to postion
	 * 
	 * @param ip
	 *            ipv4address
	 * @param port
	 *            port default 7000
	 * @param startPosition
	 *            seek postion (second)
	 * @return int result
	 * @throws
	 */
	public static int seek(String ip, int port, float startPosition) {
		if (port <= 0) {
			port = 7000;
		}
		HttpPost request = new HttpPost("http://" + ip + ":" + port + "/scrub?position=" + startPosition);
		try {
			request.setEntity(null);
			request.addHeader("User-Agent", USER_AGENT);
			HttpResponse httpResponse = httpclient.execute(request);
			L.v(TAG, "airplay open result : " + EntityUtils.toString(httpResponse.getEntity()));
			if (httpResponse.getStatusLine().getStatusCode() != 200) {
				return RS_ERROR;
			} else {
				return RS_OK;
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		return RS_ERROR;
	}

	/**
	 * pause
	 * 
	 * @param ip
	 *            ipv4address
	 * @param port
	 *            port default 7000
	 * @return int
	 * @throws
	 */
	public static int pause(String ip, int port) {
		L.v(TAG, "airone airplay pause!");
		return changePlayState(ip, port, false);
	}

	/**
	 * play
	 * 
	 * @param ip
	 *            ipv4address
	 * @param port
	 *            port default 7000
	 * @return int
	 * @throws
	 */
	public static int play(String ip, int port) {
		L.v(TAG, "airone airplay play!");
		return changePlayState(ip, port, true);
	}

	/**
	 * stop playback
	 * 
	 * @param ip
	 * @param port
	 * @return
	 * @return int
	 * @throws
	 */
	public static int stop(String ip, int port) {
		L.v(TAG, "airone airplay stop!");
		if (port <= 0) {
			port = 7000;
		}
		HttpPost request = new HttpPost("http://" + ip + ":" + port + "/stop");
		try {
			request.setEntity(null);
			request.addHeader("User-Agent", USER_AGENT);
			HttpResponse httpResponse = httpclient.execute(request);
			L.v(TAG, "airplay stop result : " + EntityUtils.toString(httpResponse.getEntity()));
			if (httpResponse.getStatusLine().getStatusCode() != 200) {
				return RS_ERROR;
			} else {
				return RS_OK;
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		return RS_ERROR;
	}

	/**
	 * Retrieve the current playback position. This can be called repeatedly to
	 * update a timeline on the client. The following parameters are returned
	 * 
	 * @param ip
	 * @param port
	 * @return float[] float[0] duration in seconds float[1] position in seconds
	 * @throws
	 */
	public static float[] getScrub(String ip, int port) {

		if (port <= 0) {
			port = 7000;
		}
		HttpGet request = new HttpGet("http://" + ip + ":" + port + "/scrub");
		try {
			request.addHeader("User-Agent", USER_AGENT);
			HttpResponse httpResponse = httpclient.execute(request);
			if (httpResponse.getStatusLine().getStatusCode() != 200) {
				return new float[] { RS_ERROR, RS_ERROR };
			} else {
				String content = EntityUtils.toString(httpResponse.getEntity());
				L.v(TAG, "airplay changePlayState result : " + content);
				String scrub[] = content.split("\n");
				if (scrub.length > 1) {
					float duration = Float.valueOf(scrub[0].substring(10));
					float position = Float.valueOf(scrub[1].substring(10));
					return new float[] { duration, position };
				} else {
					return new float[] { RS_ERROR, RS_ERROR };
				}
			}
		} catch (Exception e) {
			e.printStackTrace();
		}

		return new float[] { RS_ERROR, RS_ERROR };
	}

	/**
	 * Change the playback rate. The value argument is a float value
	 * representing the playback rate: 0 is paused, 1 is playing at the normal
	 * speed.
	 * 
	 * @param isPlay
	 *            true is change to play false is pause
	 * @return
	 * @return int
	 * @throws
	 */
	private static int changePlayState(String ip, int port, boolean isPlay) {
		if (port <= 0) {
			port = 7000;
		}
		float value = 1f;
		if (!isPlay) {
			value = 0f;
		}
		HttpPost request = new HttpPost("http://" + ip + ":" + port + "/rate?value=" + value);
		try {
			request.setEntity(null);
			request.addHeader("User-Agent", USER_AGENT);
			HttpResponse httpResponse = httpclient.execute(request);
			L.v(TAG, "airplay changePlayState result : " + EntityUtils.toString(httpResponse.getEntity()));
			if (httpResponse.getStatusLine().getStatusCode() != 200) {
				return RS_ERROR;
			} else {
				return RS_OK;
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		return RS_ERROR;
	}

}
